package com.syp.auth.web.resource;

import java.util.LinkedList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.POST;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import com.syp.auth.common.Constants;
import com.syp.auth.domain.KeyValuePair;
import com.syp.auth.domain.ProcessResult;
import com.syp.auth.domain.ValidateResult;
import com.syp.auth.domain.vo.AppVo;
import com.syp.auth.export.common.GeneralAccessVo;
import com.syp.auth.export.common.GeneralUserVo;
import com.syp.auth.export.common.SigninParamEnum;
import com.syp.auth.export.request.AppLogRequest;
import com.syp.auth.export.request.TokenVerifyRequest;
import com.syp.auth.export.resource.AuthorizeResourceI;
import com.syp.auth.export.response.AppLogResponse;
import com.syp.auth.export.response.TokenVerifyResponse;
import com.syp.auth.service.base.AppServiceI;
import com.syp.auth.service.business.AuthorizeServiceI;
import com.syp.auth.service.business.IllegalAuthenticationArgumentException;
import com.syp.auth.service.business.NoSigninAuthenticationException;
import com.syp.auth.service.business.UsernameOrPasswordUncheckException;
import com.syp.auth.service.validator.SigninError;
import com.syp.auth.service.validator.SigninValidatorI;
import com.syp.auth.service.validator.SigninVerifyStyle;

@Controller
@RequestMapping("/api/authorize")
public class AuthorizeResourceImpl implements AuthorizeResourceI {
	
	private static final Logger log = LoggerFactory.getLogger(AuthorizeResourceImpl.class);

	@Autowired
	private HttpServletRequest httpRequest;
	@Autowired
	private HttpServletResponse httpResponse;
	@Autowired
	private AuthorizeServiceI authorizeService;
	@Autowired
	private SigninValidatorI signinValidator;
	@Autowired
	private AppServiceI appService;

	@RequestMapping("/verify")
	@POST
	@ResponseBody
	@Override
	public TokenVerifyResponse verify(@RequestBody TokenVerifyRequest request) {
		TokenVerifyResponse response = new TokenVerifyResponse();

		boolean valid = this.authorizeService.verify(request);
		response.setValid(valid);
		return response;
	}

	@RequestMapping("/signin")
	public ModelAndView signin() {
		ModelAndView mv = new ModelAndView();
		try {
			List<KeyValuePair> paramList = new LinkedList<>();
			String[] paramNames = SigninParamEnum.paramNames();
			for (String pname : paramNames) {
				String value = httpRequest.getParameter(pname);
				if (value == null) {
					throw new IllegalAuthenticationArgumentException();
				}
				paramList.add(new KeyValuePair(pname, value));
			}

			String appCode = httpRequest.getParameter(SigninParamEnum.APP.getParam());
			AppVo app = appService.getByAppCode(appCode);
			SigninVerifyStyle svs = app.getVerifyStyle() == null ? SigninVerifyStyle.NONE : SigninVerifyStyle.get(app.getVerifyStyle());
			switch (svs) {
			case NONE: {
				mv.setViewName("api/signin");
				break;
			}
			case IVC: {
				mv.setViewName("api/signin.ivc");
				break;
			}
			}
			mv.addObject("paramList", paramList);
			for (KeyValuePair kv : paramList) {
				mv.addObject(kv.getKey(), kv.getValue());
			}
		} catch (IllegalAuthenticationArgumentException e) {
			mv.setViewName(String.format("redirect:%s", httpRequest.getContextPath() + Constants.INDEX_VIEW_NAME));
		}
		return mv;
	}

	@RequestMapping("/dsignin")
	@ResponseBody
	public ProcessResult dsignin(GeneralUserVo guser, GeneralAccessVo gaccess) {
		ProcessResult pr = new ProcessResult();
		try {
			if (gaccess.getReturnUrl() == null || gaccess.getSid() == null || gaccess.getApp() == null) {
				throw new IllegalAuthenticationArgumentException();
			}

			ValidateResult vr = this.signinValidator.validate(guser, gaccess);
			if (vr.isValid()) {
				this.authorizeService.dsignin(guser, gaccess, httpResponse);
				pr.setSuccess(true);
				pr.setMsg("登录成功");
			} else {
				pr.setSuccess(false);
				pr.setMsg(vr.getEmsg());
				pr.setObj(vr.getEcode());
			}
		} catch (IllegalAuthenticationArgumentException e) {
			pr.setSuccess(false);
			pr.setMsg(SigninError.illegalRequest.getEmsg());
		} catch (UsernameOrPasswordUncheckException e) {
			pr.setSuccess(false);
			pr.setMsg(SigninError.usernameOrPasswordUncheck.getEmsg());
		} catch (NoSigninAuthenticationException e) {
			pr.setSuccess(false);
			pr.setMsg(SigninError.signinAuthorizeUncheck.getEmsg());
		} catch (Exception e) {
			pr.setSuccess(false);
			pr.setMsg(SigninError.sysError.getEmsg());
		}

		return pr;
	}

	@RequestMapping("/ivc")
	@ResponseBody
	public void ivc(String sid) {
		this.authorizeService.ivc(sid, httpResponse);
	}

	@RequestMapping("/signout")
	@ResponseBody
	@Override
	public ProcessResult signout(String sid) {
		try {
			this.authorizeService.signout(sid);
		} catch (Exception e) {
			log.error("退出登录失败。", e);
		}
		return new ProcessResult(true, "退出登录成功。");
	}

	@RequestMapping("/cuser")
	@ResponseBody
	@Override
	public GeneralUserVo cuser(String sid) {
		return this.authorizeService.getCurrentUser(sid);
	}

	@RequestMapping("/capp")
	@ResponseBody
	@Override
	public AppVo capp(String app) {
		return this.appService.getByAppCode(app);
	}

	@RequestMapping("/log")
	@Override
	public AppLogResponse log(@RequestBody AppLogRequest request) {
		return this.authorizeService.log(request);
	}

}
